#ifndef BufferedVMEReader_h
#define BufferedVMEReader_h

#include <iostream>
#include <sys/types.h>
#include "FIFO32DMAReader.h"

class BufferedVMEReader
{

 protected:

    u_int32_t cell_size;            //size of one cell in words (BAS: bytes??)
    u_int32_t cell_no;              //number of cells
    u_int32_t *buffer, buffer_size;
    u_int32_t put_index;
    u_int32_t get_index;
    FIFO32DMAReader *f32dr;

 public:

    BufferedVMEReader(u_int32_t cell_size, u_int32_t cell_no, FIFO32DMAReader *f32dr)
    {
        this->cell_size = cell_size;
        this->cell_no   = cell_no;
        this->f32dr     = f32dr;

        buffer_size     = cell_size * cell_no;
        buffer          = new u_int32_t[buffer_size];
        put_index       = 0;
        get_index       = 0;
    };

    u_int32_t read(u_int32_t len, u_int32_t *buf)
    {
    	for (u_int32_t i = 0; i < len; i++) {
    	    if (wordsInBuffer() == 0) {
//              std::cout << "BufferedVMEReader::read(): reload" << std::endl;
        		f32dr->readFIFO32DMA(cell_size, buffer + put_index);
        		put_index += cell_size;
        		if (put_index > buffer_size - cell_size) 
        		    put_index = 0;
    	    }

    	    buf[i] = buffer[get_index];
    	    get_index++;
    	    if (get_index >= buffer_size)
    	        get_index = 0;	    
    	}
    	return 0;
    }

    u_int32_t readWord()
    {
    	if (wordsInBuffer() == 0) {
//  	    std::cout << "BufferedVMEReader::read(): reload" << std::endl;
    	    f32dr->readFIFO32DMA(cell_size, buffer + put_index);
    	    put_index += cell_size;
    	    if (put_index > buffer_size - cell_size) 
        		put_index = 0;
    	}

    	u_int32_t r = buffer[get_index];
    	get_index++;
    	if (get_index >= buffer_size) 
    	    get_index = 0;

    	return r;
    }

    u_int32_t wordsInBuffer()
    {
    	if (put_index >= get_index)
    	    return (put_index - get_index);
    	else
    	    return (buffer_size - get_index + put_index);
    }
	
	void clear()
	{
		put_index = get_index;
	}
};

#endif

